﻿#include "OiPCH.hpp"
#include "View/OiPixmap.hpp"
#include "Tools/OiPlyTool.hpp"

namespace Oi
{
    namespace PLScannerCore
    {
        class PointParamsDlg : public QDialog
        {
        public:
            PointParamsDlg(QWidget* parent);

            void setParams(const QVariantMap& mp);

            QVariantMap params() const;

        public:
            QGroupBox* _alarm;
            QGroupBox* _error;
            QLineEdit* _alarmTol;
            QLineEdit* _errorTol;

            QDialogButtonBox* buttons;
        };

        PointParamsDlg::PointParamsDlg(QWidget* parent) : QDialog(parent)
        {
            setWindowTitle("检测参数编辑");

            QVBoxLayout* layout = new QVBoxLayout(this);
           
            _alarmTol = new QLineEdit(this);
            _errorTol = new QLineEdit(this);

            _alarmTol->setValidator(new QDoubleValidator());
            _errorTol->setValidator(new QDoubleValidator());

            _alarm = new QGroupBox(this);
            _alarm->setTitle("预警");
            _alarm->setCheckable(true);

            _error = new QGroupBox(this);
            _error->setTitle("报警");
            _error->setCheckable(true);

            QFormLayout* alarmLayout = new QFormLayout(_alarm);
            alarmLayout->addRow("预警公差", _alarmTol);

            QFormLayout* errorLayout = new QFormLayout(_error);
            errorLayout->addRow("报警公差", _errorTol);

            buttons = new QDialogButtonBox(QDialogButtonBox::Cancel | QDialogButtonBox::Ok, this);

            layout->addWidget(_alarm);
            layout->addWidget(_error);
            layout->addWidget(buttons);
        }

        void PointParamsDlg::setParams(const QVariantMap& mp)
        {
            if (mp.contains("Enable"))
            {
                int en = mp["Enable"].toInt();
                _alarm->setChecked(en & TC_WarningEnable);
                _error->setChecked(en & TC_ErrorEnable);
            }

            if (mp.contains("WarningTol"))
            {
                double va = mp["WarningTol"].toDouble();
                _alarmTol->setText(QString::number(va, 'f', 2));
            }

            if (mp.contains("ErrorTol"))
            {
                double va = mp["ErrorTol"].toDouble();
                _errorTol->setText(QString::number(va, 'f', 2));
            }
        }

        QVariantMap PointParamsDlg::params() const
        {
            QVariantMap map;

            int en = 0xFFFF;
            if (!_alarm->isChecked())
            {
                en &= (~TC_WarningEnable);
            }

            if (!_error->isChecked())
            {
                en &= (~TC_ErrorEnable);
            }

            double wt = _alarmTol->text().toDouble();
            double et = _errorTol->text().toDouble();


            map["Enable"] = en;
            map["WarningTol"] = wt;
            map["ErrorTol"] = et;
            return map;
        }

        class PositionDlg : public QDialog
        {
        public:
            PositionDlg(QWidget* parent);

            void setPosition(const double& mp);

            double position() const;

        public:
            QLineEdit* _position;

            QDialogButtonBox* buttons;
        };

        PositionDlg::PositionDlg(QWidget* parent) : QDialog(parent)
        {
            setWindowTitle("");

            QVBoxLayout* layout = new QVBoxLayout(this);

            _position = new QLineEdit(this);
            _position->setValidator(new QDoubleValidator());

            QFormLayout* editLayout = new QFormLayout();
            editLayout->addRow("位置", _position);

            buttons = new QDialogButtonBox(QDialogButtonBox::Cancel | QDialogButtonBox::Ok, this);

            layout->addLayout(editLayout);
            layout->addWidget(buttons);
        }

        void PositionDlg::setPosition(const double& mp)
        {
            _position->setText(QString::number(mp, 'f', 2));
        }

        double PositionDlg::position() const
        {
            QVariantMap map;

            return _position->text().toDouble();
        }

        class ProductWidgetImpl : public Impl<ProductWidget>
        {
        public:
            void init(ProductMeasurePage type);
            void exit();

        public:
            void updateWidget();
            void updateParams();
            void updateMeasures();

        public:
            void clearView(int mode);

        public:
            ProductParams _params;

        public:
            QVariantMap _config;

        public:
            bool _editable;
            QString _namecpy;

        public:
            QWidget* _title;

            QLabel* _nameLabel;
            QLineEdit * _nameEdit;

            QLabel* _typeLabel;
            QComboBox* _typeEdit;
            QLabel* _thicknessLabel;
            QLineEdit* _thicknessEdit;
            QToolButton* _settings;
            QToolButton* _acquire;
            QToolButton* _create;
            QAction* _fullWidthEdit;
            QAction* _halfWidthEdit;
            QToolButton* _measure;
            QToolButton* _fixedMeasure;
            ToolProfilesView* _profileView;
            ProductMeasurePage _type;
        };

        void ProductWidgetImpl::init(ProductMeasurePage type)
        {
            OI_Q(ProductWidget);

            q->setFocusPolicy(Qt::ClickFocus);
            _editable = false;

            _type = type;

            QVBoxLayout* mainLayout = new QVBoxLayout(q);
            mainLayout->setContentsMargins(0, 0, 0, 0);

            _title = new QWidget(q);
            _title->setStyleSheet(QString("QLineEdit{background:transparent;border-width:0;border-style:outset;color:%1;font-size:10pt}"
                "QLabel{color:%1;font-size:10pt}").arg(PLScannerStyle::windowTextColor().rgb(), 6, 16, QChar('0')));

            auto tLayout = new QHBoxLayout(_title);

            _nameLabel = new QLabel(ProductWidget::tr("规格名称:"), q);
            _nameEdit = new QLineEdit(q);
            _nameEdit->setFixedWidth(120);

            _typeLabel = new QLabel(ProductWidget::tr("类型:"), q);
            _typeEdit = new QComboBox(q);
            _typeEdit->setFixedWidth(60);

            _typeEdit->addItem(ProductWidget::tr("内衬"));

            _thicknessLabel = new QLabel(ProductWidget::tr("标准宽厚差异:"), q);
           
            _thicknessEdit = new QLineEdit(q);
            _thicknessEdit->setFixedWidth(120);
            _thicknessEdit->setStyleSheet("QLabel{color: black;background-color: white;}");
           
            _nameEdit->setReadOnly(true);
            _nameEdit->installEventFilter(q);
            tLayout->addWidget(_nameLabel);
            tLayout->addWidget(_nameEdit);
            tLayout->addWidget(_typeLabel);
            tLayout->addWidget(_typeEdit);
            tLayout->addWidget(_thicknessLabel);
            tLayout->addWidget(_thicknessEdit);
            _acquire = new QToolButton(q);
            _acquire->setIcon(QIcon(":/" + PLScanner::instance()->resourceName + "/camera.png"));
            _acquire->setText(ProductWidget::tr("获取"));
            _acquire->setStyleSheet(QString("QToolButton{color:%1}QToolButton:hover,QToolButton:checked{color:black}").arg(PLScannerStyle::windowTextColor().rgb(), 6, 16, QChar('0')));
            _acquire->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
            _acquire->setCheckable(true);

            _create = new QToolButton(q);
            _create->setIcon(QIcon(":/" + PLScanner::instance()->resourceName + "/curveAnalyze.png"));
            _create->setText(ProductWidget::tr("控制点"));
            _create->setStyleSheet(QString("QToolButton{color:%1}QToolButton:hover,QToolButton:checked{color:black}").arg(PLScannerStyle::windowTextColor().rgb(), 6, 16, QChar('0')));
            _create->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
            _create->setCheckable(false);
            _create->setPopupMode(QToolButton::InstantPopup);
//             auto profileMenu = new QMenu();
//             _create->addme(profileMenu);
            _fullWidthEdit = new QAction(ProductWidget::tr("对称/非对称全宽"));
            _halfWidthEdit = new QAction(ProductWidget::tr("对称半宽"));
            _create->addAction(_fullWidthEdit);
            _create->addAction(_halfWidthEdit);

            _measure = new QToolButton(q);
            _measure->setIcon(QIcon(":/" + PLScanner::instance()->resourceName + "/measure.png"));
            _measure->setText(ProductWidget::tr("测量点"));
            _measure->setStyleSheet(QString("QToolButton{color:%1}QToolButton:hover,QToolButton:checked{color:black}").arg(PLScannerStyle::windowTextColor().rgb(), 6, 16, QChar('0')));
            _measure->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
            _measure->setCheckable(false);

            _fixedMeasure = new QToolButton(q);
            _fixedMeasure->setIcon(QIcon(":/" + PLScanner::instance()->resourceName + "/measure.png"));
            _fixedMeasure->setText(ProductWidget::tr("定点测量"));
            _fixedMeasure->setStyleSheet(QString("QToolButton{color:%1}QToolButton:hover,QToolButton:checked{color:black}").arg(PLScannerStyle::windowTextColor().rgb(), 6, 16, QChar('0')));
            _fixedMeasure->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
            _fixedMeasure->setCheckable(false);

            _settings = new QToolButton(q);
            _settings->setIcon(QIcon(":/" + PLScanner::instance()->resourceName + "/setting.png"));
            _settings->setText(ProductWidget::tr("设置"));
            _settings->setStyleSheet(QString("QToolButton{color:%1}QToolButton:hover,QToolButton:checked{color:black}").arg(PLScannerStyle::windowTextColor().rgb(), 6, 16, QChar('0')));
            _settings->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);

            tLayout->addStretch();
            tLayout->addWidget(_create);
            tLayout->addWidget(_measure);
            tLayout->addWidget(_fixedMeasure);
            tLayout->addWidget(_acquire);
            tLayout->addWidget(_settings);

            _title->setEnabled(false);
            mainLayout->addWidget(_title);

            _profileView = new ToolProfilesView(q);
            mainLayout->addWidget(_profileView);

            _profileView->setPageFlag(_type);

            if (_type == PMP_ThicknessMeasure)
            {
                _fixedMeasure->hide();
            }
            else if (_type == PMP_FixedMeasure)
            {
                _measure->hide();
            }

            q->connect(_nameEdit, &QLineEdit::editingFinished, q, &ProductWidget::onEditFinished);
            q->connect(_typeEdit, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), q, &ProductWidget::onTypeChanged);

            q->connect(_settings, &QToolButton::clicked, q, &ProductWidget::onSetting);
            q->connect(_acquire, &QToolButton::clicked, q, &ProductWidget::onAcquire);
            q->connect(_fullWidthEdit, &QAction::triggered, q, &ProductWidget::onCreate);
            q->connect(_halfWidthEdit, &QAction::triggered, q, &ProductWidget::onCreate);
            q->connect(_measure, &QToolButton::clicked, q, &ProductWidget::onMeasure);
            q->connect(_fixedMeasure, &QToolButton::clicked, q, &ProductWidget::onFixedMeasure);
            q->connect(_profileView, &ToolProfilesView::toolDoubleClicked, q, &ProductWidget::onEditTool);
            q->connect(_profileView, &ToolProfilesView::addToolComplete, q, &ProductWidget::onAddTool);
            q->connect(_profileView, &ToolProfilesView::delTool, q, &ProductWidget::onDelTool);

            q->connect(SensorAcquire::OiAcquire(), &SensorAcquire::enterAcquire, q, &ProductWidget::onEnterAcquire);
            q->connect(SensorAcquire::OiAcquire(), &SensorAcquire::leaveAcquire, q, &ProductWidget::onLeaveAcquire);
            
        }

        void ProductWidgetImpl::exit()
        {
            
        }

        void ProductWidgetImpl::updateWidget()
        {
            OI_Q(ProductWidget);
            
        }
       
        void ProductWidgetImpl::updateParams()
        {

        }

        void ProductWidgetImpl::updateMeasures()
        {
            OI_Q(ProductWidget);
            auto& mps = _params.measureThickness;
            QList<int> dels;
            for (int i = 0; i < mps.size(); i++)
            {
                auto& mp = mps[i];

                if (mp.x() > _params.materialsWidth / 2 || mp.x() < -_params.materialsWidth / 2)
                {
                    dels << i;
                }
                else
                {
                    if (_params.profiles.size() > 0)
                    {
                        mp.setY(PLScannerUtil::y_at_profile(_params.profiles[0], mp.x()));
                    }
                    else
                    {
                        dels << i;
                    }
                }
            }

            for (int i = 0; i < dels.size(); i++)
            {
                q->onDelTool(i);
            }

            if (_params.fixedPoint.x() > _params.materialsWidth / 2 || _params.fixedPoint.x() < -_params.materialsWidth / 2)
            {
                _params.fixedPoint.setY(PLScannerUtil::y_at_profile(_params.profiles[0], _params.fixedPoint.x()));
            }
            else
            {
                if (_params.profiles.size() > 0)
                {
                    _params.fixedPoint = QPointF(0.0, PLScannerUtil::y_at_profile(_params.profiles[0], 0.0));
                }
            }

        }

        void ProductWidgetImpl::clearView(int mode)
        {
           
        }

        ProductWidget::ProductWidget(ProductMeasurePage type, QWidget * parent /*= nullptr*/) : QWidget(parent)
        {
            OI_I(ProductWidget)->init(type);
        }

        ProductWidget::~ProductWidget()
        {
            OI_E(ProductWidget)->exit();
        }

        void ProductWidget::setParams(const QString name, const ProductParams params)
        {
            OI_F(ProductWidget);

            d->_nameEdit->setText(name);
            d->_params = params;
            d->_params.specName = name;
            d->_namecpy = name;
            d->_profileView->setParams(params);
            QString strKey = QString("%1/ThicknessValue").arg(name);
//            QString pricision = Core::OiSettings()->object()->value(strKey).toString();
            QDir tempDir;
            
            QString tempFilePath = tempDir.currentPath() + "\\settings\\" + "formual.ini";  // currentPath()方法返回应用程序所在的当前目录；

            QSettings settings(tempFilePath, QSettings::Format::IniFormat);
            QString pricision = settings.value(strKey, 0.00).toString();
            double thickness = settings.value(strKey, 0.00).toDouble();
            if (thickness == 0.00)
            {
                pricision = Core::OiSettings()->value("Measure/EdgeThickness").toString();
            }
            d->_thicknessEdit->setText(pricision);
        }

        void ProductWidget::updateParams()
        {
            OI_F(ProductWidget);

            d->_profileView->setParams(d->_params);
        }

        ProductParams ProductWidget::parmas()
        {
            OI_F(ProductWidget);
            return d->_params;
        }

        QString ProductWidget::name() const
        {
            return OI_IMPL()->_nameEdit->text();
        }

        void ProductWidget::setEditable(bool enable)
        {
            OI_F(ProductWidget);
            d->_editable = enable;
            d->_title->setEnabled(enable);
           // d->_nameEdit->setReadOnly(!enable);
            d->_profileView->setEditable(enable);
            d->_thicknessEdit->setStyleSheet("QLabel{color: black;background-color: white;}");
        }
        QString ProductWidget::getThicknessValue()
        {
            OI_F(ProductWidget);
            return d->_thicknessEdit->text();
        }
        bool ProductWidget::eventFilter(QObject *obj, QEvent *evt)
        {
            OI_F(ProductWidget);

            if(evt->type() == QEvent::MouseButtonDblClick)
            {
                auto edit = qobject_cast<QLineEdit*>( obj );
                if (edit && d->_editable)
                {
                    edit->setReadOnly(false);
                    edit->selectAll();
                    edit->setStyleSheet("background:white;border-width:0;border-style:outset;color:black;font-size:10pt");
                    return true;
                }
            }

            return QObject::eventFilter(obj, evt);
        }

        void ProductWidget::onEnterAcquire()
        {
            OI_F(ProductWidget);
            d->_acquire->blockSignals(true);
            d->_acquire->setChecked(true);
            d->_acquire->blockSignals(false);
        }

        void ProductWidget::onLeaveAcquire()
        {
            OI_F(ProductWidget);
            d->_acquire->blockSignals(true);
            d->_acquire->setChecked(false);
            d->_acquire->blockSignals(false);
        }

        void ProductWidget::setProfile(const OiProfiles& profiles)
        {
            OI_F(ProductWidget);
        }

        void ProductWidget::setConfig(QVariantMap config)
        {
              OI_IMPL()->_config = config;
        }

        void ProductWidget::onEditFinished()
        {
            OI_F(ProductWidget);

            auto edit = qobject_cast<QLineEdit*>( sender() );

            edit->setReadOnly(true);
            edit->setStyleSheet(QString("background:transparent;border-width:0;border-style:outset;color:%1;font-size:10pt")
                .arg(PLScannerStyle::windowTextColor().rgb(), 6, 16, QChar('0')));

            if(d->_editable)
            {
                if(edit == d->_nameEdit)
                {
                    auto name = edit->text();

                    if (name != d->_namecpy && ProductParams::checkName(name))
                    {
                        for (int i = 0; i < 99; i++)
                        {
                            auto temp = name + "_" + QString::number(i);
                            if (!ProductParams::checkName(temp))
                            {
                                edit->setText(temp);
                                d->_params.specName = temp;
                                break;
                            }
                        }
                        OiAlerter() << tr("已存在当前配方");
                    }
                    else
                    {
                        d->_params.specName = name;
                    }
                }
            }
        }

        void ProductWidget::onSetting()
        {
            OI_F(ProductWidget);

        }

        void ProductWidget::onAcquire()
        {
            OI_F(ProductWidget);
        }

        void ProductWidget::onCreate()
        {
            OI_F(ProductWidget);

            QObject* s = sender();

            if (s == d->_halfWidthEdit)
            {
                DefinitionEditDlg dlg(DT_HalfWidth, this);
                dlg.setParams(d->_params);
                dlg.resize(1600, 600);
                dlg.exec();
                d->_params = dlg.params();
                d->updateMeasures();

                updateParams();
            }
            else if (s == d->_fullWidthEdit)
            {
                DefinitionEditDlg dlg(DT_FullWidth, this);
                dlg.setParams(d->_params);
                dlg.resize(1600, 600);
                dlg.exec();
                d->_params = dlg.params();
                d->updateMeasures();

                updateParams();
            }
        }

        void ProductWidget::onClearView()
        {
            OI_F(ProductWidget);
        }

        void ProductWidget::onTypeChanged()
        {

        }

        void ProductWidget::onMeasure()
        {
            OI_F(ProductWidget);

            d->_profileView->addMeasureTool();
        }

        void ProductWidget::onFixedMeasure()
        {

        }

        void ProductWidget::addToolProfilesViewPoint(QPointF point)
        {
            OI_F(ProductWidget);
            d->_profileView->addMeasurePoint(point);
        }

        void ProductWidget::onEditTool(const int id, const int type)
        {
            OI_F(ProductWidget);
            if (!d->_editable)
            {
                return;
            }

            QVariantMap values;

            if (d->_params.insParams.contains(id))
            {
                QVariantMap pamras = d->_params.insParams[id].value<QVariantMap>();
                if (type == 0)
                {
                    if (pamras.contains("x"))
                    {
                        values = pamras["x"].value<QVariantMap>();
                    }
                }
                else
                {
                    if (pamras.contains("y"))
                    {
                        values = pamras["y"].value<QVariantMap>();
                    }
                }
            }

            if (values.isEmpty())
            {
                if (id >= TT_MeasureThicknessTool && id < TT_FixedPointMeasure)
                {
                    int index = id - TT_MeasureThicknessTool;
                    double pos = 0.0;
                    if (type == 0)
                    {
                        pos = d->_params.measureThickness[index].x();
                    }
                    else
                    {
                        pos = d->_params.measureThickness[index].y();
                    }

                    PositionDlg dlg(this);

                    dlg.setPosition(pos);

                    connect(dlg.buttons, &QDialogButtonBox::accepted, &dlg, &QDialog::accept);
                    connect(dlg.buttons, &QDialogButtonBox::rejected, &dlg, &QDialog::reject);

                    if (dlg.exec() == QDialog::Accepted)
                    {
                        pos = dlg.position();

                        if (type == 0)
                        {
                            auto mp = d->_profileView->setMeasureToolPos(index, pos);
                            d->_params.measureThickness[index] = mp;
                        }
                        else
                        {

                        }
                    }
                }
                else if (id == TT_FixedPointMeasure)
                {
                    double pos = 0.0;
                    if (type == 0)
                    {
                        pos = d->_params.fixedPoint.x();
                    }
                    else
                    {
                        pos = d->_params.fixedPoint.y();
                    }

                    PositionDlg dlg(this);

                    dlg.setPosition(pos);

                    connect(dlg.buttons, &QDialogButtonBox::accepted, &dlg, &QDialog::accept);
                    connect(dlg.buttons, &QDialogButtonBox::rejected, &dlg, &QDialog::reject);

                    if (dlg.exec() == QDialog::Accepted)
                    {
                        pos = dlg.position();

                        if (type == 0)
                        {
                            auto mp = d->_profileView->setFixedMeasurePos(pos);
                            d->_params.fixedPoint = mp;
                        }
                        else
                        {

                        }
                    }
                }
            }
            else
            {
                PointParamsDlg dlg(this);

                dlg.setParams(values);

                connect(dlg.buttons, &QDialogButtonBox::accepted, &dlg, &QDialog::accept);
                connect(dlg.buttons, &QDialogButtonBox::rejected, &dlg, &QDialog::reject);

                if (dlg.exec() == QDialog::Accepted)
                {
                    values = dlg.params();

                    QVariantMap pamras = d->_params.insParams[id].value<QVariantMap>();

                    if (type == 0)
                    {
                        pamras["x"] = QVariant::fromValue(values);
                    }
                    else
                    {
                        pamras["y"] = QVariant::fromValue(values);
                    }

                    d->_params.insParams[id] = QVariant::fromValue(pamras);
                }
            }
        }

        void ProductWidget::onAddTool(const QPointF p)
        {
            OI_F(ProductWidget);
            if (!d->_editable)
            {
                return;
            }

            d->_params.measureThickness.append(p);
            d->_params.insParams[TT_MeasureThicknessTool + d->_params.measureThickness.size() - 1]
                = QVariant::fromValue(PlyTool::toolDefaultValues(TT_MeasureThicknessTool));

        }

        void ProductWidget::onDelTool(const int id)
        {
            OI_F(ProductWidget);
            if (!d->_editable)
            {
                return;
            }

            d->_params.measureThickness.removeAt(id);

            QVariantList paramsList;

            for (auto iter = d->_params.insParams.begin(); iter != d->_params.insParams.end();)
            {
                if (iter.key() >= TT_MeasureThicknessTool && iter.key() < TT_FixedPointMeasure)
                {
                    if (iter.key() != TT_MeasureThicknessTool + id)
                    {
                        paramsList.push_back(iter.value());
                    }

                    iter = d->_params.insParams.erase(iter);
                }
                else
                {
                    iter++;
                }
            }

            for (int i = 0; i < paramsList.size(); i++)
            {
                d->_params.insParams[TT_MeasureThicknessTool + i] = paramsList[i];
            }
           
        }

    }
}